package com.bridgeintelligent.tag.remotefile.nas;


import com.bridgeintelligent.tag.remotefile.RemoteFileHandler;
import com.bridgeintelligent.tag.remotefile.fastdfs.FastDFSException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;

@Slf4j
public class NasHandler implements RemoteFileHandler {

    static final char SEPARATOR = File.separatorChar;
    private NasConfigProps props;
    private static Set<PosixFilePermission> permissions, folderPermission;
    private static final int FAILED = 999;
    static {
        permissions = new HashSet<>();
        permissions.add(PosixFilePermission.OWNER_READ);
        permissions.add(PosixFilePermission.OWNER_WRITE);
        permissions.add(PosixFilePermission.GROUP_READ);
        permissions.add(PosixFilePermission.OTHERS_READ);
        folderPermission = new HashSet<>();
        folderPermission.add(PosixFilePermission.OWNER_READ);
        folderPermission.add(PosixFilePermission.OWNER_WRITE);
        folderPermission.add(PosixFilePermission.OWNER_EXECUTE);
        folderPermission.add(PosixFilePermission.GROUP_READ);
        folderPermission.add(PosixFilePermission.GROUP_EXECUTE);
        folderPermission.add(PosixFilePermission.OTHERS_READ);
        folderPermission.add(PosixFilePermission.OTHERS_EXECUTE);
    }

    public NasHandler(NasConfigProps props) {
        this.props = props;
    }

    @Override
    public String upload(String localFilename,String fileName) {
        FileInfo info = new FileInfo(localFilename);
        String remoteFilename = props.getRemoteStorage() + SEPARATOR + fileName+ info.extension;
        File file = new File(remoteFilename);
        try {
            FileUtils.copyFile(new File(localFilename), file);
        } catch (Exception e) {
            log.error("发生异常------->>>",e);
            throw new NasException(FAILED, e);
        }
        remoteFilename = remoteFilename.replace(props.getRemoteStorage(), props.getReturnStorage());
        delete(localFilename);
        setPermissions(file);
        return remoteFilename;
    }

    @Override
    public String uploadFile(String localFilename, String picName) {
        String remoteFilename = props.getRemoteStorage() + SEPARATOR + picName + ".jpg";
        File file = new File(remoteFilename);
        try {
            FileUtils.copyFile(new File(localFilename), file);
        } catch (Exception e) {
            throw new NasException(FAILED, e);
        }
        remoteFilename = remoteFilename.replace(props.getRemoteStorage(), props.getReturnStorage());
        delete(localFilename);
        setPermissions(file);
        return remoteFilename;
    }

    @Override
    public String download(String remoteFilename) {
        remoteFilename = remoteFilename.replace(props.getReturnStorage(), props.getRemoteStorage());
        FileInfo info = new FileInfo(remoteFilename);
        String localFilename = props.getLocalStorage() + SEPARATOR + info.fullname;
        try {
            FileUtils.copyFile(new File(remoteFilename), new File(localFilename));
        } catch (IOException e) {
            throw new NasException(FAILED, e);
        }
        return localFilename;
    }

    public static void main(String[] args) {
        String a = "//784C0792E4A4406CBBA82CB5F4244ABE.drl";
        System.out.println(a.replace("//", "/home/qyuser/mgm_work/static/imgs/"));
    }

    @Override
    public String writeLocal(MultipartFile file) {
        if (file.isEmpty()) {
            throw new FastDFSException(10002, "The file of upload is empty!");
        }
        String fileName = file.getOriginalFilename();
        String savepath = props.getLocalStorage() + File.separator + fileName;
        File dest = new File(savepath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        OutputStream out = null;
        InputStream is = null;
        byte[] bs = null;
        try {
            bs = file.getBytes();
            out = new FileOutputStream(savepath);
            is = new ByteArrayInputStream(bs);
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = is.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            return savepath;
        } catch (Exception e) {
            throw new NasException(FAILED, e);
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }

    @Override
    public String writeLocalWithFileName(MultipartFile file,String fileName) {
        if (file.isEmpty()) {
            throw new FastDFSException(10002, "The file of upload is empty!");
        }
        FileInfo fileInfo=new FileInfo(file.getOriginalFilename());
        String savepath = props.getLocalStorage() + File.separator + fileName+fileInfo.extension;
        File dest = new File(savepath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        OutputStream out = null;
        InputStream is = null;
        byte[] bs = null;
        try {
            bs = file.getBytes();
            out = new FileOutputStream(savepath);
            is = new ByteArrayInputStream(bs);
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = is.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            return savepath;
        } catch (Exception e) {
            throw new NasException(FAILED, e);
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(out);
        }
    }

    @Override
    public int delete(String remoteFilename) {
        remoteFilename = remoteFilename.replace(props.getReturnStorage(), props.getRemoteStorage());
        try {
            FileUtils.deleteQuietly(new File(remoteFilename));
        } catch (Exception e) {
            e.printStackTrace();
            return 1;
        }
        return 0;
    }

    @Override
    public String uploadWithActivity(String localFilename, String activityId) {
        String filePath = props.getRemoteStorage() + SEPARATOR + activityId;
        mkdirFolder(filePath);
        FileInfo info = new FileInfo(localFilename);
        String remoteFilename = filePath + SEPARATOR + activityId + info.extension;
        File file = new File(remoteFilename);
        try {
            FileUtils.copyFile(new File(localFilename), file);
        } catch (Exception e) {
            log.error("localFile----->>>"+localFilename+"\n");
            log.error("上传文件发生异常,异常名为"+e.getMessage(),e);
            throw new NasException(FAILED, e);
        }
        remoteFilename = remoteFilename.replace(props.getRemoteStorage(), props.getReturnStorage());
        delete(localFilename);
        setPermissions(file);
        return remoteFilename;
    }

    @Override
    public String uploadWhiteList(String localFileName, String activityId) {
        String path = uploadWithActivity(localFileName, activityId);
        path = path.replace(props.getReturnStorage(), "");
        return props.getRemoteStorage() + path;
    }

    @Override
    public int delDirectory(String directoryName) {
        directoryName = props.getRemoteStorage() + "/" + directoryName;
        try {
            FileUtils.deleteDirectory(new File(directoryName));
        } catch (Exception e) {
            e.printStackTrace();
            return 1;
        }
        return 0;
    }

    @Override
    public String getRemoteFile(String remoteFilename) {
        remoteFilename = props.getRemoteStorage() + remoteFilename;
        FileInfo info = new FileInfo(remoteFilename);
        String localFilename = props.getLocalStorage() + SEPARATOR + info.fullname;
        try {
            FileUtils.copyFile(new File(remoteFilename), new File(localFilename));
        } catch (IOException e) {
            throw new NasException(FAILED, e);
        }
        return localFilename;
    }

    @Override
    public byte[] downloadForByte(String remoteFilename) {
        try {
            FileUtils.readFileToByteArray(new File(remoteFilename));
        } catch (Exception e) {
            throw new NasException(FAILED, e);
        }
        return null;
    }

    private static void mkdirFolder(String folderName) {
        File file = new File(folderName);
        if (!file.exists()) {
            if (file.mkdir()) {
                setFolderPermission(folderName);
            }
        }
    }

    private static void setFolderPermission(String folderPath) {
        Path path = Paths.get(folderPath);
//        try {
//            Files.setPosixFilePermissions(path, folderPermission);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    private static void setPermissions(File file) {
        Path path = Paths.get(file.getAbsolutePath());
//        try {
//            Files.setPosixFilePermissions(path, permissions);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    static class FileInfo {

        String fullname;
        String firstname;
        String extension;

        FileInfo(String filename) {
            File file = new File(filename);
            fullname = file.getName();
            int i = fullname.lastIndexOf(".");
            if (i >= 0) {
                extension = fullname.substring(i);
            } else {
                extension = "";
            }
            firstname = fullname.replace(extension, "");
        }
    }

    @Override
    public String writeByPath(MultipartFile multipartFile,String path, String fileName){
        if (multipartFile.isEmpty()) {
            throw new FastDFSException(10002, "The file of upload is empty!");
        }
        mkdirFolders(path);
        String filePath = path + SEPARATOR + fileName;
        byte[] bs = null;
        try {
            bs = multipartFile.getBytes();
        } catch (IOException e) {
            throw new NasException(FAILED, e);
        }
        File file = new File(filePath);
        try(OutputStream out = new FileOutputStream(file);
            InputStream is = new ByteArrayInputStream(bs)) {
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = is.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(is);
            return filePath;
        } catch (Exception e) {
            log.error("上传文件失败",e);
            throw new NasException(FAILED, e);
        }
    }

    @Override
    public String getPath(String path){
        return props.getRemoteStorage() +  path;
    }

    private static void mkdirFolders(String folderName) {
        File file = new File(folderName);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    @Override
    public String uploadByPath(String localFileName, String path, String fileName) {
        mkdirFolder(path);
        String remoteFilename = path + SEPARATOR + fileName;
        File file = new File(remoteFilename);
        try {
            FileUtils.copyFile(new File(localFileName), file);
        } catch (Exception e) {
            log.error("localFile----->>>"+localFileName+"\n");
            log.error("上传文件发生异常,异常名为"+e.getMessage(),e);
            throw new NasException(FAILED, e);
        }
        delete(localFileName);
        setPermissions(file);
        return remoteFilename;
    }

    @Override
    public String getParentPath(String activityId) {
        return props.getRemoteStorage() + SEPARATOR + activityId + SEPARATOR;
    }
}
